#ifndef MYTHCDG_CPP
#define MYTHCDG_CPP

#include <qapplication.h>
#include <mythtv/mythcontext.h>
#include <mythtv/uitypes.h>
#include <mythtv/lcddevice.h>

using namespace std;

#include "songtree.h"
#include "songhandler.h"
#include <qdir.h>
#include <qfile.h>

#include "CDGWidget.h"

#ifdef USING_OPENGL    
#include "CDGWidgetGL.h"
#endif

QString KaraokeTreeItem::getFillSql(QString layer) const
{
    unsigned childDepth = m_depth + 1;
    bool childIsLeaf = childDepth == m_root->getDepth();
    QString childLevel = m_root->getLevel(childDepth - 1);
    QString filter = m_root->getFilter();
    QString columns;

    if (childLevel == "name")
    {
        columns = childIsLeaf
            ? "name, title, filepath, type, containerpath"
            : "name";

        if(layer.length() == 1)
           filter += " and name like '" + layer + "%'";

    }
    else if (childLevel == "hash") {
        columns = "upper(left(name,1))";
    }

    filter += " and hostname='" + gContext->GetHostName() + "'";

    QString conj = "where ";
    if (!filter.isEmpty())
    {
        filter = conj + filter;
    }


    QString sql;
    sql = "select distinct "
        + columns
        + " from cdgmetadata "
        + filter
        + " order by name"
        + ";";

    return sql;
}

KaraokeTreeItem* KaraokeTreeItem::createChild(QSqlQuery *query) const
{
    KaraokeTreeItem *childItem = new KaraokeTreeItem(m_root);
    childItem->m_depth = m_depth + 1;

    QString current = query->value(0).toString().stripWhiteSpace();
    if (childItem->isLeaf())
    {
        SongInfo tmp;
        tmp.setName(query->value(0).toString());
        tmp.setTitle(query->value(1).toString());
        tmp.setFilePath(query->value(2).toString());
        tmp.setType(query->value(3).toString());
        tmp.setContainerPath(query->value(4).toString());

        childItem->m_songInfo = new SongInfo(tmp);
    }
    else
    {
        childItem->m_songInfo = m_songInfo
                             ? new SongInfo(*m_songInfo)
                             : new SongInfo();
        if (childItem->getLevel() == "hash")
           childItem->m_songInfo->setName(current);
        else
           childItem->m_songInfo->setField(childItem->getLevel(), current);
    }

    return childItem;
}



/**************************************************************************
    SongTree
 **************************************************************************/
SongTree::SongTree(MythMainWindow *parent, QString windowName,
                 QString themeFilename, const char *name)
    : MythThemedDialog(parent, windowName, themeFilename, name),
      cdg(0)
{
    KaraokeTreeRoot *root;
    GenericTree *node;
    m_karaokeTree = new GenericTree("Karaoke",0,false);

    imagetimer = new QTimer( this ); 
    connect( imagetimer, SIGNAL(timeout()),  SLOT(showImageTimeout()) ); 

    wireUpTheme();

#ifdef USING_OPENGL
    if(gContext->GetNumSetting("CdgUseOpenGL"))
    {
        cdg = new CDGWidgetGL(this);
    }
    else
#endif
    {
        cdg = new CDGWidget(this);
    }

    //Setup handlers
    SongHandler::count();

    //DVD: iso
    root = new KaraokeTreeRoot("name","type='dvd'");
    m_karaokeTreeRoots.push_back(root);
    m_karaokeTreeItems.push_back(new KaraokeTreeItem(root));
    node = m_karaokeTree->addNode("DVDs",  m_karaokeTreeItems.size(), false);

    //CDG: .cdg
    root = new KaraokeTreeRoot("hash name","type='cdg'");
    m_karaokeTreeRoots.push_back(root);
    m_karaokeTreeItems.push_back(new KaraokeTreeItem(root));
    node = m_karaokeTree->addNode("CDGs",  m_karaokeTreeItems.size(), false);

    m_karaokeTreeUI->assignTreeData(m_karaokeTree);
    m_karaokeTreeUI->enter();
    m_karaokeTreeUI->pushDown();

    //LCD
    LCD *lcd = LCD::Get();
    if (lcd)
       lcd->switchToTime();

    updateForeground();
}


SongTree::~SongTree()
{
    if(imagetimer)
       delete imagetimer;
    delete m_karaokeTree;
}


void SongTree::keyPressEvent(QKeyEvent *e)
{
    bool handled = false;
    QStringList actions;
    gContext->GetMainWindow()->TranslateKeyPress("CDG", e, actions);

    for (unsigned int i = 0; i < actions.size() && !handled; i++)
    {
        QString action = actions[i];
        handled = true;

        cerr << "Got: "<<action<<endl;
        if (action == "SELECT")
            m_karaokeTreeUI->select();
        else if (action == "MENU")
            cerr << "MENU" << endl;

        // Navigate in the list
        else if (action == "UP")
            m_karaokeTreeUI->moveUp();
        else if (action == "DOWN")
            m_karaokeTreeUI->moveDown();
        else if (action == "LEFT")
            m_karaokeTreeUI->popUp();
        else if (action == "RIGHT")
            m_karaokeTreeUI->pushDown();
        else if (action == "PAGEUP")
            m_karaokeTreeUI->pageUp();
        else if (action == "PAGEDOWN")
            m_karaokeTreeUI->pageDown();

        // CDG
        else if (action == "FFWD" && cdg->isActive())
           cdg->seekforward();
        else if (action == "RWND" && cdg->isActive())
           cdg->seekback();
        else if (action == "ESCAPE" && cdg->isActive())
           cdg->stop();        
        else if (action == "PAUSE" && cdg->isActive())
           cdg->pause();
        else if (action == "INFO" && cdg->isActive())
           cdg->info();
        else if (action == "1" && cdg->isActive())
           cdg->switchTransparency();
        else if (action == "2" && cdg->isActive())
           cdg->switchTransparentBkg();

        // List
        else if (action == "INFO" && !cdg->isActive())
           cout << "INFO in list" << endl;

        else
            handled = false;
    }

    if (!handled)
        MythThemedDialog::keyPressEvent(e);
}


void SongTree::wireUpTheme(void)
{
    m_karaokeTreeUI = getUIManagedTreeListType("songtreelist");
    if (!m_karaokeTreeUI)
    {
        cerr << "SongTree.o: Couldn't find a songtreelist in your theme" << endl;
        exit(0);
    }
    m_karaokeTreeUI->showWholeTree(true);
    m_karaokeTreeUI->colorSelectables(true);

    connect(m_karaokeTreeUI, SIGNAL(nodeSelected(int, IntVector*)),
            this, SLOT(handleTreeListSelection(int, IntVector*)));
    connect(m_karaokeTreeUI, SIGNAL(nodeEntered(int, IntVector*)),
            this, SLOT(handleTreeListEntry(int, IntVector*)));

    m_karaokeTitle = getUITextType("songtitle");
    if (!m_karaokeTitle)
        cerr << "karaoketree.o: Couldn't find a text area songtitle\n";

    m_karaokePath = getUITextType("songpath");
    if (!m_karaokePath)
        cerr << "karaoketree.o: Couldn't find a text area songpath\n";

    m_karaokeImage = getUIImageType("songimage");
    if (!m_karaokeImage)
        cerr << "karaoketree.o: Couldn't find an image songimage\n";
}

void SongTree::handleTreeListEntry(int nodeInt, IntVector *)
{
//    cerr << "entry" << endl;
    KaraokeTreeItem *item = nodeInt ? m_karaokeTreeItems[nodeInt - 1] : 0;
    SongInfo *songInfo = item ? item->getSongInfo() : 0;

    if (item && !item->isLeaf())
    {
        GenericTree *node = m_karaokeTreeUI->getCurrentNode();
        if (!node)
        {
            cerr << "SongTree.o: Couldn't get current node\n";
            return;
        }
        if (!item->isFilled())
        {
            node->deleteAllChildren();
            fillNode(node);
        }
    } 
    if(songInfo)
    {
        m_karaokeTitle->SetText(songInfo->getTitle());

        m_karaokePath->SetText(songInfo->getFilePath());
        QString test = songInfo->getFilePath().replace( QRegExp("iso$"), "jpg" );

        if (item->isLeaf() && QFile(test).exists())
        {
            m_karaokeImage->SetImage(test);
            if ( imagetimer->isActive() ) 
               imagetimer->changeInterval(330); 
            else 
               imagetimer->start(330, true);
        }
        else
        {
            if ( imagetimer->isActive() )
               imagetimer->stop();   

            m_karaokeImage->SetImage("");
            if (m_karaokeImage->isShown())
               m_karaokeImage->hide();
        }
    }
    else
    {
        m_karaokeTitle->SetText("");
        m_karaokePath->SetText("");

        if ( imagetimer->isActive() )
           imagetimer->stop();

        if (m_karaokeImage->isShown())
           m_karaokeImage->hide();
    }
}

void SongTree::showImageTimeout(void) 
{ 
    m_karaokeImage->LoadImage(); 
    if (!m_karaokeImage->isShown())
       m_karaokeImage->show();
} 

void SongTree::handleTreeListSelection(int nodeInt, IntVector *)
{
    if (nodeInt > 0)
    {
        KaraokeTreeItem *item = nodeInt ? m_karaokeTreeItems[nodeInt - 1] : 0;

        if (item->isLeaf())
        {            
            Playsong(item->getSongInfo());
            raise();
            setActiveWindow();
        }
    }
}

void SongTree::Playsong(SongInfo *songdata)
{
    if(songdata->getType() == "dvd")
    {
        cerr << "playing dvd!" << endl;
        cerr << "Use path: " << songdata->getFilePath() << endl;

        QString cmd = gContext->GetSetting("CdgDVDPlayer");

        if (cmd.contains("%s"))
           cmd.replace("'%s'", songdata->getFilePath());
        else
           cmd = cmd + "'" + songdata->getFilePath() + "'";

        cerr << "Running: " << cmd << endl;
        myth_system(cmd);
    }

    if(songdata->getType() == "cdg")
    {
        //LCD
        LCD *lcd = LCD::Get();
        if (lcd)
        {
            QPtrList<LCDTextItem> textItems;
            textItems.setAutoDelete(true);
            textItems.append(new LCDTextItem(
                             1, ALIGN_CENTERED, songdata->getTitle(), "Generic", true));
            lcd->switchToGeneric(&textItems);
        }

        QString songpath = songdata->getFilePath();

        cerr << "playing cdg!" << endl;
        cerr << "Use path: " << songpath << endl;

        // Check if a container
        if(songdata->isContainer()){
           songpath = SongHandler::extractpackage(*songdata);
           cerr << "Container: " << songpath << endl;
        }

        if(!cdg->play(songpath,
                      gContext->GetNumSetting("CdgUseTransparency"),
                      gContext->GetNumSetting("CdgUseBkgTransparency"),
                      gContext->GetNumSetting("CdgUseBorderTransparency")))
        {
            cerr << "playing song error" << endl;
            MythPopupBox::showOkPopup(gContext->GetMainWindow(), 
                                      QString("Playing song error"),
                                      QString("Can't open file: %1")
                                      .arg(songpath));
        }
    }
}

void SongTree::fillNode(GenericTree *node)
{
    int i = node->getInt();
    KaraokeTreeItem* curItem = m_karaokeTreeItems[i - 1];
    QString layername = node->getString();
    
    MSqlQuery query(MSqlQuery::InitCon());
    QString sql = curItem->getFillSql(layername);
    query.exec(sql);
    
    cout << "SQL: " << sql << endl;
    if (query.isActive() && query.size() > 0)
    {
        while (query.next())
        {
            KaraokeTreeItem *childItem = curItem->createChild(&query);
            m_karaokeTreeItems.push_back(childItem);

            //Create the new node
            node->addNode(childItem->getSongInfo()->getTitle(),
                          m_karaokeTreeItems.size(),
                          childItem->isLeaf());
        }
    }
    curItem->setFilled(true);
}

#endif
